import glob
import os
import re
import pandas as pd
from dotenv import load_dotenv

load_dotenv()

# 公共配置
store_dir = os.getenv('store_dir')
excel_pattern = os.getenv('excel_pattern', '*.xlsx')


def get_server_config(ip_folder):
    """
    根据 IP 文件夹名（如 '10.80.16.96'）提取配置前缀（如 '96'）
    并加载对应的服务器配置（host, user, password）
    """
    # 从 IP 地址中提取最后一段作为前缀（例如 '10.80.16.96' → '96'）
    prefix = ip_folder.split('.')[-1]
    config = {
        'host': os.getenv(f"{prefix}_host"),
        'user': os.getenv(f"{prefix}_user"),
        'password': os.getenv(f"{prefix}_password")
    }
    # 检查配置是否完整
    if not all(config.values()):
        raise ValueError(f"IP {ip_folder} 对应的配置 {prefix}_host, {prefix}_user, {prefix}_password 未正确设置")
    return config


def process_ip_folder(ip_folder):
    """处理单个 IP 对应的文件夹"""
    # 加载服务器配置
    server_config = get_server_config(ip_folder)

    # 构建路径
    input_dir = os.path.join('excel_data', ip_folder)
    output_dir = os.path.join('output_script', ip_folder)

    # 校验输入目录
    if not os.path.isdir(input_dir):
        print(f"警告：跳过无效目录 {input_dir}")
        return

    # 获取所有Excel文件
    excel_files = glob.glob(os.path.join(input_dir, excel_pattern))
    if not excel_files:
        print(f"警告：目录 {input_dir} 中没有Excel文件")
        return

    # 创建输出目录
    os.makedirs(output_dir, exist_ok=True)

    # 处理每个Excel文件
    for excel_path in excel_files:
        process_excel_file(excel_path, server_config, output_dir)


def process_excel_file(excel_path, server_config, output_dir):
    """处理单个Excel文件"""
    excel_name = os.path.basename(excel_path)
    xls = pd.ExcelFile(excel_path)
    print(f"\n处理文件: {excel_name} (IP: {server_config['host']})")

    for sheet in xls.sheet_names:
        df = pd.read_excel(excel_path, sheet_name=sheet, header=None)
        process_sheet(excel_name, sheet, df, server_config, output_dir)


# 从 Excel 文件名提取数据库名称：去掉扩展名及末尾形如 _日期 的部分
def extract_database_name(file_name):
    """改进版：仅当文件名末尾有_8位日期时，才去除日期部分"""
    base_name = os.path.splitext(os.path.basename(file_name))[0]

    # 新正则表达式：匹配结尾处 _YYYYMMDD 格式的日期
    db_name = re.sub(r'_\d{8}$', '', base_name)
    return db_name


def extract_date_info(table_name):
    """
    增强版日期解析：
    支持格式：
        prefix_YYYY
        prefix_YYYY_MM
        prefix_YYYY_MM_DD
        prefix_YYYYMM
    返回：
        (prefix, year, month)
    """
    # 匹配日期部分（支持带分隔符和不带分隔符）
    pattern = r"""
        ^(.*?)                    # 基础前缀
        (?:_|$)                   # 分隔符或结束
        (20\d{2})                 # 年份（2000-2099）
        (?:_?(\d{1,2}))?         # 月份（可选）
        (?:_\d{1,2})*$           # 日或其他后缀（忽略）
    """
    match = re.match(pattern, table_name, re.VERBOSE)

    if match:
        prefix = match.group(1).rstrip('_')
        year = match.group(2)
        month = match.group(3)

        # 处理不带分隔符的格式（如202309 → 2023,09）
        if not month and len(year) == 6 and year.isdigit():
            real_year = year[:4]
            month = year[4:6].lstrip('0')
            year = real_year
        return prefix, year, month
    return table_name, None, None


def process_sheet(excel_name, sheet_name, df, server_config, output_dir):
    """处理单个Sheet页"""

    database_name = extract_database_name(excel_name)
    # 新增调试日志
    print(f"[DEBUG] 文件名: {excel_name} → 库名: {database_name}")
    dump_commands = []
    drop_commands = []
    used_dump_files = {}

    # 根据列数判断表名列
    col_index = 1 if df.shape[1] >= 2 else 0

    for _, row in df.iterrows():
        table = str(row[col_index]).strip() if pd.notna(row[col_index]) else ""
        if not table:
            continue

        # 提取前缀及日期信息
        prefix, year, month = extract_date_info(table)

        # ============== 新增逻辑：从 prefix 中去除末尾的序号 ==============
        # 示例：bkp_capital_his_12 → bkp_capital_his
        base_prefix = re.sub(r'(_\d+)+$', '', prefix)
        # ==============================================================

        # 统一存放目录：store_dir/数据库名/基础前缀
        dump_dir = os.path.join(store_dir, database_name, base_prefix)

        # 生成带日期的文件名
        if year and month:
            output_filename = f"{base_prefix}_{year}_{month}.sql.gz"
        elif year:
            output_filename = f"{base_prefix}_{year}.sql.gz"
        else:
            output_filename = f"{base_prefix}.sql.gz"

        # 处理路径格式
        dump_path = os.path.join(dump_dir, output_filename).replace("\\", "/")

        # 判断是否追加写入（保持原有逻辑）
        operator = ">>" if dump_path in used_dump_files else ">"
        if operator == ">":
            used_dump_files[dump_path] = True


        # 使用 os.path.join 后，将路径中的反斜杠替换为正斜杠
        dump_path = os.path.join(dump_dir, output_filename).replace("\\", "/")

        # 判断该 dump_path 是否已经生成过命令
        if dump_path in used_dump_files:
            operator = ">>"
        else:
            operator = ">"
            used_dump_files[dump_path] = True

        # 生成 mysqldump 命令（注意：数据库中的表名仍使用原始 table 名）
        dump_commands.append(f'echo "Dumping table {table}..."')  # 新增日志
        cmd = (
            f"mysqldump -u{server_config['user']} -p'{server_config['password']}' "
            f"-h{server_config['host']} --set-gtid-purged=OFF {database_name} {table} "
            f"| gzip {operator} {dump_path}"
        )
        dump_commands.append(cmd)

        drop_commands.append(f'-- Dropping table {database_name}.{table}')
        drop_commands.append(f"drop table if exists {database_name}.{table};")

        # 输出文件路径
    excel_base = os.path.splitext(os.path.basename(excel_name))[0]
    dump_file = os.path.join(output_dir, f"mysqldump_{excel_base}_{sheet_name}.sh")
    drop_file = os.path.join(output_dir, f"drop_{excel_base}_{sheet_name}.sql")

    # 将 mysqldump 命令写入文件
    with open(dump_file, 'w', encoding='utf8', newline='\n') as f:
        f.write(f"# mysqldump commands for sheet: {sheet_name}\n")
        for cmd in dump_commands:
            f.write(cmd + "\n")

    # 将 drop table 语句写入文件
    with open(drop_file, 'w', encoding='utf8', newline='\n') as f:
        f.write(f"-- Drop table statements for sheet: {sheet_name}\n")
        for cmd in drop_commands:
            f.write(cmd + "\n")

    print(f"Processed sheet '{sheet_name}': {len(dump_commands)} dump commands generated.")




def main():
    """主函数：遍历 input 下所有IP文件夹并处理"""
    # 获取 input 目录下所有子文件夹（IP地址）
    ip_folders = [
        name for name in os.listdir('excel_data')
        if os.path.isdir(os.path.join('excel_data', name))
    ]

    if not ip_folders:
        raise ValueError("input 目录下没有有效的IP文件夹")

    # 处理每个IP文件夹
    for ip_folder in ip_folders:
        try:
            print(f"\n======= 开始处理IP: {ip_folder} =======")
            process_ip_folder(ip_folder)
        except Exception as e:
            print(f"处理IP {ip_folder} 时出错: {str(e)}")


if __name__ == '__main__':
    main()
